package org.jeecg.modules.system.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiSnsGetuserinfoBycodeRequest;
import com.dingtalk.api.request.OapiUserGetuserinfoRequest;
import com.dingtalk.api.response.OapiProcessinstanceGetResponse;
import com.dingtalk.api.response.OapiSnsGetuserinfoBycodeResponse;
import com.dingtalk.api.response.OapiUserGetuserinfoResponse;
import com.taobao.api.ApiException;
import com.xkcoding.justauth.AuthRequestFactory;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.jeecg.common.api.ding.DingApi;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.PasswordUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.config.Constant;
import org.jeecg.modules.controller.UserManagerController;
import org.jeecg.modules.dinguser.entity.DiyDingUser;
import org.jeecg.modules.dinguser.service.IDiyDingUserService;
import org.jeecg.modules.service.impl.DiyProfessorInfoServiceImpl;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.service.ISysUserService;
import org.jeecg.modules.util.AccessTokenUtil;
import org.jeecg.modules.util.LoginUtil;
import org.jeecg.modules.util.UserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.RowSet;
import java.io.IOException;
import java.util.List;

/**
 * @Author wangyueniao
 * @since 2020-12-8
 */
@Controller
@RequestMapping("/thirdLogin")
@Slf4j
public class ThirdLoginController {
	@Autowired
	private ISysUserService sysUserService;

	@Autowired
	private ISysBaseAPI sysBaseAPI;
	@Autowired
    private RedisUtil redisUtil;
	@Autowired
	private AuthRequestFactory factory;
	@Autowired
	private IDiyDingUserService dingUserService;
	@Autowired
	private RestTemplate restTemplate;
	@Autowired
	private DingApi dingApi;
	@RequestMapping("/render/{source}")
    public void render(@PathVariable("source") String source, HttpServletResponse response) throws IOException {
        log.info("第三方登录进入render：" + source);
        AuthRequest authRequest = factory.get(source);
        String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
        log.info("第三方登录认证地址：" + authorizeUrl);
        response.sendRedirect(authorizeUrl);
    }

	@RequestMapping("/{source}/callback")
		public String login( AuthCallback callback,ModelMap modelMap) throws ApiException {
		String source="dingtalk";
		log.info("第三方登录进入callback：" + source + " params：" + JSONObject.toJSONString(callback));
        Result<JSONObject> result = new Result<JSONObject>();
		String code=callback.getCode();
        if(code!=null) {
			OapiSnsGetuserinfoBycodeResponse response = LoginUtil.getLoginUserInfo(code);
			log.info("response"+response);
        	String realname = response.getUserInfo().getNick();
        	String uuid = response.getUserInfo().getUnionid();
			log.info("uuid"+uuid);
        	//判断有没有这个人
        	LambdaQueryWrapper<SysUser> query = new LambdaQueryWrapper<SysUser>();
        	query.eq(SysUser::getThirdId, uuid);
        	query.eq(SysUser::getThirdType, source);
        	List<SysUser> thridList = sysUserService.list(query);
        	SysUser user;
        	String token="";
        	if(thridList==null || thridList.size()==0){
        		log.info("判断有没有这个人----》没有这个人");
        		//不存在，什么也不做
				token = JwtUtil.sign("-1", "-1");
			}
			else{
				log.info("判断有没有这个人----》居然有这个人");
				user=thridList.get(0);
				//已存在 只设置真实姓名 不设置头像
				user.setRealname(realname);
				sysUserService.updateById(user);
				token = JwtUtil.sign(user.getUsername(), user.getPassword());
			}
			// 生成token
			redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
			//设置超时时间
			redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 1000);
			modelMap.addAttribute("token", token);
        }else {
			result.setSuccess(false);
			result.setMessage("第三方登录异常,请联系管理员");
		}
        return "thirdLogin";
    }

	@SuppressWarnings("unchecked")
	@RequestMapping(value = "/getLoginUser/{token}", method = RequestMethod.GET)
	@ResponseBody
	public Result<JSONObject> getLoginUser(@PathVariable("token") String token, HttpServletRequest request,HttpServletResponse response) throws Exception {
		Result<JSONObject> result = new Result<JSONObject>();
		String username = JwtUtil.getUsername(token);
		log.info("校验用户是否有效");
		//1. 校验用户是否有效
		SysUser sysUser = sysUserService.getUserByName(username);
		result = sysUserService.checkUserIsEffective(sysUser);
		if(!result.isSuccess()) {
            JSONObject obj = new JSONObject();
			//用户登录信息
			SysUser errorUser = new SysUser();
			errorUser.setUsername("-1");
			errorUser.setRealname("-1");
			obj.put("userInfo", errorUser);
			//token 信息
			obj.put("token", token);
			result.setResult(obj);
			result.setCode(200);
			result.setSuccess(false);
			log.info("校验用户是否有效-------》用户无效");
			result.setMessage("您未加入钉钉组织，请联系相关人员先加入组织！");
			return result;
		}
		log.info("校验用户是否有效-------》居然用户有效");
		JSONObject obj = new JSONObject();
		result.setCode(200);
		//根据username也就是unionid来判断是否为企业内部人员
		String userid = UserUtil.contactTypebyUnionid(username);
		log.info("userid----->"+userid);
		boolean falg = UserUtil.getuserinfobyuserid(userid);
		log.info("falg---------->>"+falg);
		if(!falg){
			//用户登录信息
			obj.put("userInfo",sysUser);
			//token 信息
			result.setResult(obj);
			result.setSuccess(false);
			result.setMessage("您未加入钉钉组织，请联系相关人员先加入组织！");
		}
		else {
			//用户登录信息
			obj.put("userInfo",sysUser);
			//token 信息
			obj.put("token", token);
			result.setResult(obj);
			result.setSuccess(true);
			sysBaseAPI.addLog("用户名: " + username + ",登录成功[第三方用户]！", CommonConstant.LOG_TYPE_1, null);
		}
		return result;
	}
	@RequestMapping(value = "/queryByCodeUser/{code}", method = RequestMethod.GET)
	@ResponseBody
	public Result<JSONObject> queryByCodeUser(@PathVariable("code") String code) throws ApiException {
		Result<JSONObject> result = new Result<JSONObject>();
		DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/getuserinfo");
		OapiUserGetuserinfoRequest req = new OapiUserGetuserinfoRequest();
		req.setCode(code);
		req.setHttpMethod("GET");
		OapiUserGetuserinfoResponse rsp = client.execute(req,AccessTokenUtil.getToken());
		String bd = rsp.getBody();
		JSONObject object = JSON.parseObject(bd);
		//获取userId
		String userId = object.getString("userid");
		log.info("queryByCodeUser获取到的userid=====>"+userId);
		String unionid = dingApi.getUnionIdByUserId(userId);
		log.info("queryByCodeUser获取到的unionid=====>"+userId);
		SysUser user = new SysUser();
		user.setUsername(unionid);
		user.setPassword(code);
		String token = JwtUtil.sign(user.getUsername(),user.getPassword());
		redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
		// 设置超时时间
//		log.info("内部应用免登陆设置永不过期");
		redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 1000);
//		redisUtil.persist(CommonConstant.PREFIX_USER_TOKEN + token);
		JSONObject obj = new JSONObject();
		//token 信息
		log.info("开始保存token=====>"+token.toString());
		obj.put("token", token);
		result.setResult(obj);
		result.setCode(200);
		result.setSuccess(true);
		return result;
	}

}
